import json
from typing import Dict

from django.conf import settings
from django.utils.translation import gettext_lazy as _
from django.core.cache import cache as dj_cache

from ceph.models import GlobalConfig


def set_settings_key(key, value):
    setattr(settings, key, value)


def check_old_conf_name():
    """ 临时版本增加，需要修改参数名称 """
    conf_cls_qs = GlobalConfig.objects.all()
    if not conf_cls_qs:
        return

    for qs in conf_cls_qs:
        if qs.name == 'siteName':
            qs.name = GlobalConfig.ConfigName.SITE_NAME.value
            qs.save()
        elif qs.name == 'poweredBy':
            qs.name = GlobalConfig.ConfigName.POWER_BY.value
            qs.save()

        elif qs.name == 'ftpCertFilePath':
            qs.name = GlobalConfig.ConfigName.FTP_CERT_FILE_PATH.value
            qs.save()

        elif qs.name == 'ftpLogPath':
            qs.name = GlobalConfig.ConfigName.FTP_LOG_PATH.value
            qs.save()

        elif qs.name == 'passportJwt':
            qs.name = GlobalConfig.ConfigName.AAI_JWT_VERIFYING_KEY.value
            qs.save()

        elif qs.name == 'resourceAdministrator':
            qs.name = GlobalConfig.ConfigName.RESOURCE_ADMINISTRATOR.value
            qs.save()

        elif qs.name == 's3ServiceUrl':
            qs.name = GlobalConfig.ConfigName.S3_SERVICE_URL.value
            qs.save()

        elif qs.name == 'emailConfig':
            qs.name = GlobalConfig.ConfigName.EMAIL_CONFIG.value
            qs.save()

        elif qs.name == 'ftpDomainName':
            qs.name = GlobalConfig.ConfigName.FTP_DOMAIN_NAME.value
            qs.save()

        elif qs.name == 'userRegister':
            qs.name = GlobalConfig.ConfigName.USER_REGISTER.value
            qs.save()

        elif qs.name == 's3ApiEnable':
            qs.name = GlobalConfig.ConfigName.S3_API_ENABLE.value
            qs.save()

        elif qs.name == 'nextCloudDatabase':
            qs.name = GlobalConfig.ConfigName.NEXTCLOUD_DATABASE.value
            qs.save()

        elif qs.name == 'nextCloudS3ServiceUrl':
            qs.name = GlobalConfig.ConfigName.NEXTCLOUD_S3_SERVICE_URL.value
            qs.save()

        elif qs.name == 'nextCloudServiceUrl':
            qs.name = GlobalConfig.ConfigName.NEXTCLOUD_SERVICE_URL.value
            qs.save()

        elif qs.name == 'nextCloudAdminAccount':
            qs.name = GlobalConfig.ConfigName.NEXTCLOUD_ADMIN_ACCOUNT.value
            qs.save()

        elif qs.name == 'localEndpoint':
            qs.name = GlobalConfig.ConfigName.LOCAL_ENDPOINT.value
            qs.save()

        elif qs.name == 'yunkunAuthName':
            qs.name = GlobalConfig.ConfigName.YUNKUN_AUTH_NAME.value
            qs.save()

        elif qs.name == 'yunkunAuthEndpoint':
            qs.name = GlobalConfig.ConfigName.YUNKUN_AUTH_ENDPOINT.value
            qs.save()


def save_qs(qs, old_qs):
    if old_qs:
        qs.content = old_qs.content
        qs.save()


def check_old_conf_name2(conf_qs):
    """ 临时版本增加，需要修改参数名称 """
    if conf_qs:
        conf_cls_qs = conf_qs
    else:
        conf_cls_qs = GlobalConfig.objects.all()
        if not conf_cls_qs:
            return

    for qs in conf_cls_qs:
        if qs.name == GlobalConfig.ConfigName.SITE_NAME.value:
            old_qs = GlobalConfig.objects.filter(name='siteName').first()
            save_qs(qs=qs, old_qs=old_qs)
        elif qs.name == GlobalConfig.ConfigName.POWER_BY.value:
            old_qs = GlobalConfig.objects.filter(name='poweredBy').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.FTP_CERT_FILE_PATH.value:
            old_qs = GlobalConfig.objects.filter(name='ftpCertFilePath').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.FTP_LOG_PATH.value:
            old_qs = GlobalConfig.objects.filter(name='ftpLogPath').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.AAI_JWT_VERIFYING_KEY.value:
            old_qs = GlobalConfig.objects.filter(name='passportJwt').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.RESOURCE_ADMINISTRATOR.value:
            old_qs = GlobalConfig.objects.filter(name='resourceAdministrator').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.S3_SERVICE_URL.value:
            old_qs = GlobalConfig.objects.filter(name='s3ServiceUrl').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.EMAIL_CONFIG.value:
            old_qs = GlobalConfig.objects.filter(name='emailConfig').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.FTP_DOMAIN_NAME.value:
            old_qs = GlobalConfig.objects.filter(name='ftpDomainName').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.USER_REGISTER.value:
            old_qs = GlobalConfig.objects.filter(name='userRegister').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.S3_API_ENABLE.value:
            old_qs = GlobalConfig.objects.filter(name='s3ApiEnable').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.NEXTCLOUD_DATABASE.value:
            old_qs = GlobalConfig.objects.filter(name='nextCloudDatabase').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.NEXTCLOUD_SERVICE_URL.value:
            old_qs = GlobalConfig.objects.filter(name='nextCloudServiceUrl').first()
            save_qs(qs=qs, old_qs=old_qs)
        elif qs.name == GlobalConfig.ConfigName.NEXTCLOUD_S3_SERVICE_URL.value:
            old_qs = GlobalConfig.objects.filter(name='nextCloudS3ServiceUrl').first()
            save_qs(qs=qs, old_qs=old_qs)

        elif qs.name == GlobalConfig.ConfigName.NEXTCLOUD_ADMIN_ACCOUNT.value:
            old_qs = GlobalConfig.objects.filter(name='nextCloudAdminAccount').first()
            save_qs(qs=qs, old_qs=old_qs)


class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__call__(*args, **kwargs)

        return cls._instance


class Configs(metaclass=Singleton):
    ConfigName = GlobalConfig.ConfigName
    CACHE_KEY = 'iharbor_app_global_configs_cache'

    @staticmethod
    def get_configs_no_cache(remove_invalid: bool = False) -> Dict[str, str]:
        # check_old_conf_name()
        qs = GlobalConfig.objects.all().values('name', 'content')
        configs = {}
        invalid_names = []
        conf_names = GlobalConfig.ConfigName.values
        for cfg in qs:
            name = cfg['name']
            if name in conf_names:
                configs[cfg['name']] = cfg['content']
            else:
                invalid_names.append(name)

        if remove_invalid and invalid_names:
            GlobalConfig.objects.filter(name__in=invalid_names).delete()

        # 缺少配置
        if len(configs) < len(conf_names):
            for name in conf_names:
                if name not in configs:
                    def_values = GlobalConfig.value_defaults[name]
                    if isinstance(def_values, dict):
                        value = def_values.get('content', '')
                        remark = def_values.get('remark', '')
                    else:
                        value = def_values
                        remark = ''

                    obj, created = GlobalConfig.objects.get_or_create(
                        name=name, defaults={'content': value, 'remark': remark})
                    configs[name] = obj.content

        return configs

    @staticmethod
    def get_configs() -> Dict[str, str]:
        cache_key = Configs.CACHE_KEY
        configs = dj_cache.get(cache_key)
        if configs:
            return configs

        configs = Configs.get_configs_no_cache(remove_invalid=False)
        dj_cache.set(cache_key, configs, timeout=120)

        if configs[GlobalConfig.ConfigName.S3_SERVICE_URL.value]:
            configs[GlobalConfig.ConfigName.S3_SERVICE_URL.value] = GlobalConfig.parse_lines(text=configs[GlobalConfig.ConfigName.S3_SERVICE_URL.value])

        if configs[GlobalConfig.ConfigName.NEXTCLOUD_S3_SERVICE_URL.value]:
            configs[GlobalConfig.ConfigName.NEXTCLOUD_S3_SERVICE_URL.value] = GlobalConfig.parse_lines(text=configs[GlobalConfig.ConfigName.NEXTCLOUD_S3_SERVICE_URL.value])

        if configs[GlobalConfig.ConfigName.S3_API_ENABLE.value]:
            configs[GlobalConfig.ConfigName.S3_API_ENABLE.value] = True if configs[GlobalConfig.ConfigName.S3_API_ENABLE.value] in ['true', 'True'] else False

        if configs[GlobalConfig.ConfigName.NEXTCLOUD_DATABASE.value]:
            configs[GlobalConfig.ConfigName.NEXTCLOUD_DATABASE.value] = json.loads(configs[GlobalConfig.ConfigName.NEXTCLOUD_DATABASE.value])

        s3_server_http_host_name = getattr(settings, 'S3_SERVER_HTTP_HOST_NAME', None)
        if not s3_server_http_host_name and GlobalConfig.ConfigName.S3_SERVICE_URL.value in configs:
            set_settings_key(key='S3_SERVER_HTTP_HOST_NAME',
                             value=configs[GlobalConfig.ConfigName.S3_SERVICE_URL.value])
        elif s3_server_http_host_name and GlobalConfig.ConfigName.S3_SERVICE_URL.value in configs and s3_server_http_host_name != \
                configs[GlobalConfig.ConfigName.S3_SERVICE_URL.value]:
            set_settings_key(key='S3_SERVER_HTTP_HOST_NAME',
                             value=configs[GlobalConfig.ConfigName.S3_SERVICE_URL.value])

        passport_jwt = getattr(settings, 'PASSPORT_JWT', None)
        if passport_jwt and GlobalConfig.ConfigName.AAI_JWT_VERIFYING_KEY.value in configs and passport_jwt[
            'VERIFYING_KEY'] != configs[GlobalConfig.ConfigName.AAI_JWT_VERIFYING_KEY.value]:
            settings.PASSPORT_JWT['VERIFYING_KEY'] = configs[GlobalConfig.ConfigName.AAI_JWT_VERIFYING_KEY.value]
            # set_settings_key(key=settings.PASSPORT_JWT['VERIFYING_KEY'], value=configs['passportJwt'])

        use_s3_api = getattr(settings, 'USE_S3_API', '')
        if not configs[GlobalConfig.ConfigName.S3_API_ENABLE.value]:
            settings.USE_S3_API = True

        if not use_s3_api:
            set_settings_key(key='USE_S3_API', value=configs[GlobalConfig.ConfigName.S3_API_ENABLE.value])
        elif use_s3_api and use_s3_api != configs[GlobalConfig.ConfigName.S3_API_ENABLE.value]:
            set_settings_key(key='USE_S3_API', value=configs[GlobalConfig.ConfigName.S3_API_ENABLE.value])

        # nextcloud_databases = getattr(settings, 'NEXTCLOUD_DATABASE', None)
        nextcloud_databases = getattr(settings, 'DATABASES', None)
        if nextcloud_databases:
            nextcloud_db = {'nextcloud': configs[GlobalConfig.ConfigName.NEXTCLOUD_DATABASE.value]}
            settings.DATABASES.update(nextcloud_db)
            # set_settings_key(key='NEXTCLOUD_DATABASE', value=configs['nextCloudDatabase'])

        nextcloud_s3 = getattr(settings, 'NEXTCLOUD_S3_SERVICE_URL', None)
        if not nextcloud_s3:
            set_settings_key(key='NEXTCLOUD_S3_SERVICE_URL',
                             value=configs[GlobalConfig.ConfigName.NEXTCLOUD_S3_SERVICE_URL.value])

        return configs

    @staticmethod
    def clear_cache():
        dj_cache.delete(Configs.CACHE_KEY)

    def get(self, name: str):
        """
        查询参数
        """
        if name not in GlobalConfig.ConfigName.values:
            raise Exception(_('未知的全局参数'))

        configs = self.get_configs()
        return configs[name]

    def check_site_parameter_resource_admin(self):
        """ 检查站点参数：中坤管理员格式 """
        qs = GlobalConfig.objects.filter(name=GlobalConfig.ConfigName.RESOURCE_ADMINISTRATOR.value).first()
        if not qs:
            return

        if ',' in qs.content:
            content_list = qs.content.split(',')
            qs.content = '\n'.join(content_list)
            qs.save(update_fields=['content'])
        elif '，' in qs.content:
            content_list = qs.content.split('，')
            qs.content = '\n'.join(content_list)
            qs.save(update_fields=['content'])
        else:
            raise Exception(f'未识别到","或"，"格式，具体信息如下：\n{qs.content}')


    def check_site_parameter_nexcloud_s3(self):
        """ 检查和修正 nextcloud s3 参数"""
        qs_s3 = GlobalConfig.objects.filter(name=GlobalConfig.ConfigName.NEXTCLOUD_S3_SERVICE_URL.value).first()
        qs = GlobalConfig.objects.filter(name=GlobalConfig.ConfigName.NEXTCLOUD_SERVICE_URL.value).first()

        if not qs_s3 or not qs:
            return

        if ',http://127.0.0.1:8025' in qs_s3.content:
            a = qs_s3.name
            b = qs.name

            qs_s3.name = b
            qs_s3.save(update_fields=['name'])
            qs.name = a
            qs.save(update_fields=['name'])

            if ',' in qs_s3.content:
                content_list = qs_s3.content.split(',')
                qs_s3.content = '\n'.join(content_list)
                qs_s3.save(update_fields=['content'])
            elif '，' in qs_s3.content:
                content_list = qs_s3.content.split('，')
                qs_s3.content = '\n'.join(content_list)
                qs_s3.save(update_fields=['content'])
            else:
                raise Exception(f'未识别到","或"，"格式，具体信息如下：\n{qs_s3.content}')

        else:

            if ',' in qs.content:
                content_list = qs.content.split(',')
                qs.content = '\n'.join(content_list)
                qs.save(update_fields=['content'])
            elif '，' in qs.content:
                content_list = qs.content.split('，')
                qs.content = '\n'.join(content_list)
                qs.save(update_fields=['content'])
            else:
                raise Exception(f'未识别到","或"，"格式，具体信息如下：\n{qs.content}')



global_configs = Configs()
